package com.nali.dal.mongo.dao;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import com.nali.dal.dao.IQueryDao;
import com.nali.dal.exception.TooManyResultException;
import com.nali.dal.expression.ExpressionValue;
import com.nali.dal.expression.PropertyExpression;
import com.nali.dal.expression.query.Criteria;
import com.nali.dal.mongo.dao.general.ExceptionTraner;
import com.nali.dal.mongo.explain.query.Find;
import com.nali.dal.mongo.explain.query.PreparedFind;

public class MongoQueryDao implements IQueryDao {
	private DBCollection collection;

	public MongoQueryDao(DBCollection collection) {
		this.collection = collection;
	}
	
	@Override
	public List<Map<String, Object>> queryForLimit(List<PropertyExpression<Criteria>> pcs,
					List<ExpressionValue<Criteria>> crs, int offset, int limit) {
		PreparedFind preparedFind = Find.parse(pcs, crs);
		try {
			return preparedFind.find(Collections.emptyList(), collection, offset, limit);
		} catch (Exception e) {
			throw ExceptionTraner.tranException(e);
		}
	}

	@Override
	public List<Map<String, Object>> queryForList(List<PropertyExpression<Criteria>> pcs, List<ExpressionValue<Criteria>> crs) {
		return queryForLimit(pcs, crs, 0, 0);
	}

	@Override
	public Map<String, Object> queryForObject(List<PropertyExpression<Criteria>> pcs, List<ExpressionValue<Criteria>> crs) {
		List<Map<String, Object>> list = queryForList(pcs, crs);// TODO 可以在更底层支持
		if (list.size() > 1) {
			throw new TooManyResultException(list.size());
		}
		return list.size() == 0 ? null : list.get(0);
	}

	@Override
	public Map<String, Object> queryOne(List<PropertyExpression<Criteria>> pcs, List<ExpressionValue<Criteria>> crs) {
		List<Map<String, Object>> list = queryForLimit(pcs, crs, 0, 1);
		return list.size() == 0 ? null : list.get(0);
	}

	@Override
	public long count(List<PropertyExpression<Criteria>> pcs, List<ExpressionValue<Criteria>> crs) {
		PreparedFind preparedFind = Find.parse(pcs, crs);
		try {
			return preparedFind.count(Collections.emptyList(), collection);
		} catch (MongoException e) {
			throw ExceptionTraner.tranException(e);
		}
	}

}
